package bll

import (
	"fmt"
	"time"

	"public.com/goutil/syncUtil"

	"7qule.com/sd3/CrossServer/src/bll/kuangzhan/dal"
	. "7qule.com/sd3/CrossServer/src/bll/kuangzhan/model"
	"7qule.com/sd3/CrossServer/src/bll/world"
	"7qule.com/sd3/CrossServer/src/common/onlinelog"
	"7qule.com/sd3/CrossServer/src/common/systemConstant"
)

// 镖局信息务逻辑类
type globalKuangzhanOccupyBll struct {
	// 镖局信息数据
	data map[string]*GlobalKuangzhanOccupy

	// 数据同步对象
	dataLock *syncUtil.RWLocker
}

// --------------------------------初始化--------------------------------------------------

// 镖局信息逻辑类
var GlobalKuangzhanOccupyBll = &globalKuangzhanOccupyBll{
	dataLock: syncUtil.NewRWLocker(),
}

// 初始化
func init() {
	// 注册数据初始化函数
	world.LoadMgr.RegisterFunc(GlobalKuangzhanOccupyBll.StructName(), GlobalKuangzhanOccupyBll.initData)
}

// StructName 模块名
func (this *globalKuangzhanOccupyBll) StructName() string {
	return "GlobalKuangzhanOccupyBll"
}

//
// initData
// @Description:初始化数据
// @receiver this
// @return errList:错误信息
//
func (this *globalKuangzhanOccupyBll) initData() (errList []error) {

	tempList, err := dal.GlobalKuangzhanOccupyDal.GetData()
	if err != nil {
		errList = append(errList, err)
		return
	}

	tempMap := make(map[string]*GlobalKuangzhanOccupy)

	for _, item := range tempList {
		tempMap[item.PlayerId] = item
	}
	this.data = tempMap

	return
}

// --------------------------------生成的基础方法--------------------------------------------------

//
// GetData
// @Description:获取数据
// @receiver this
// @return map[string]*GlobalKuangzhanOccupy:获取到的镖局占领信息数据
//
func (this *globalKuangzhanOccupyBll) GetData() map[string]*GlobalKuangzhanOccupy {
	return this.data
}

// --------------------------------内部方法--------------------------------------------------

//
// insert
// @Description: 插入数据
// @receiver this
// @param data:数据对象
//
func (this *globalKuangzhanOccupyBll) insert(data *GlobalKuangzhanOccupy) {
	dal.GlobalKuangzhanOccupyDal.Insert(data)
}

//
// update
// @Description:更新数据
// @receiver this
// @param data:数据对象
//
func (this *globalKuangzhanOccupyBll) update(data *GlobalKuangzhanOccupy) {
	dal.GlobalKuangzhanOccupyDal.Update(data)
}

//
// delete
// @Description:删除数据
// @receiver this
// @param data:数据对象
//
func (this *globalKuangzhanOccupyBll) delete(data *GlobalKuangzhanOccupy) {
	dal.GlobalKuangzhanOccupyDal.Delete(data)
}

//
// initPlayerOccupyInfo
// @Description:新建玩家占领信息
// @receiver this
// @param playerId:用户id
// @param occupyTime:占领时间
// @return *GlobalKuangzhanOccupy:占领信息
//
func (this *globalKuangzhanOccupyBll) initPlayerOccupyInfo(playerId string, occupyTime time.Time) *GlobalKuangzhanOccupy {
	if isOk, prevStack, currStack := this.dataLock.Lock(systemConstant.DefaultLockTime); isOk == false {
		errMsg := fmt.Sprintf("Lock timeout! \n上一个堆栈:\n%s  \n当前堆栈:\n%s", prevStack, currStack)
		onlinelog.ErrorLog(errMsg)
		panic(errMsg)
	}
	defer this.dataLock.Unlock()

	data := NewGlobalKuangzhanOccupy2(playerId, occupyTime)
	this.data[playerId] = data

	return data
}

// --------------------------------外部方法--------------------------------------------------

//
// GetPlayerOccupyInfo
// @Description:获取用户占领信息
// @receiver this
// @param playerId:用户id
// @return data:占领信息
// @return exist:占领信息是否存在
//
func (this *globalKuangzhanOccupyBll) GetPlayerOccupyInfo(playerId string) (data *GlobalKuangzhanOccupy, exist bool) {
	if isOk, prevStack, currStack := this.dataLock.RLock(systemConstant.DefaultLockTime); isOk == false {
		errMsg := fmt.Sprintf("Lock timeout! \n上一个堆栈:\n%s  \n当前堆栈:\n%s", prevStack, currStack)
		onlinelog.ErrorLog(errMsg)
		panic(errMsg)
	}
	defer this.dataLock.RUnlock()

	data, exist = this.data[playerId]
	return
}

//
// UpdatePlayerOccupyInfo
// @Description:更新用户占领镖局信息
// @receiver this
// @param playerId:用户id
// @param occupyTime:占领时间
// @return *GlobalKuangzhanOccupy:用户占领镖局信息
//
func (this *globalKuangzhanOccupyBll) UpdatePlayerOccupyInfo(playerId string, occupyTime time.Time) (data *GlobalKuangzhanOccupy) {
	// 读锁
	data, exist := this.GetPlayerOccupyInfo(playerId)
	if !exist {
		// 写锁
		data = this.initPlayerOccupyInfo(playerId, occupyTime)
		this.insert(data)

		return data
	}

	data.PlayerId = playerId
	data.OccupyTime = occupyTime
	this.update(data)

	return
}

//
// ReceivePlayerIncome
// @Description:获取用户收益
// @receiver this
// @param playerId:用户id
// @return income:收益
//
func (this *globalKuangzhanOccupyBll) ReceivePlayerIncome(playerId string) (income int64) {
	data, exist := this.GetPlayerOccupyInfo(playerId)
	if !exist {
		return
	}

	nowTime := time.Now()
	occupyTime := data.OccupyTime

	income = nowTime.Unix() - occupyTime.Unix()

	data.OccupyTime = nowTime
	this.update(data)

	return
}

//
// DeletePlayerOccupy
// @Description:删除用户占领信息
// @receiver this
// @param playerId:用户id
//
func (this *globalKuangzhanOccupyBll) DeletePlayerOccupy(playerId string) {
	if isOk, prevStack, currStack := this.dataLock.Lock(systemConstant.DefaultLockTime); isOk == false {
		errMsg := fmt.Sprintf("Lock timeout! \n上一个堆栈:\n%s  \n当前堆栈:\n%s", prevStack, currStack)
		onlinelog.ErrorLog(errMsg)
		panic(errMsg)
	}
	defer this.dataLock.Unlock()

	this.delete(this.data[playerId])
	delete(this.data, playerId)
}
